package com.cardone.platform.authority.dao;

import java.util.List;
import java.util.Map;
import java.util.UUID;

import lombok.Getter;
import lombok.Setter;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import com.cardone.common.dto.PaginationDto;
import com.cardone.common.util.EntityUtils;
import com.cardone.context.Attributes;
import com.cardone.context.ContextHolder;
import com.cardone.persistent.builder.Model;
import com.cardone.persistent.builder.ModelArgs;
import com.cardone.persistent.builder.ModelUtils;
import com.cardone.persistent.support.JdbcTemplateSupport;
import com.cardone.persistent.support.PaginationArgs;
import com.cardone.platform.authority.dto.PermissionDto;
import com.google.common.collect.Maps;

/**
 * 许可
 *
 * @author yaohaitao
 *
 */
@Getter
@Setter
public class PermissionJdbcDao implements PermissionDao {
	@Override
	public int deleteByIds(final PermissionDto deletePermission) {
		final Model model = ModelUtils.newModel();

		if (MapUtils.isNotEmpty(deletePermission.getAttrs())) {
			model.putAll(deletePermission.getAttrs());
		}

		model.put(Attributes.ids.name(), deletePermission.getIds());

		model.putTrue(Model.Keys.whereAndBetween.stringValue(), Attributes.sysdate.name());

		return ContextHolder.getBean(JdbcTemplateSupport.class).update(SqlIds.deleteByIds.id(), model);
	}

	@Override
	public <P> P findByCodeOrId(final Class<P> mappedClass, final PermissionDto findPermission) {
		final String[] whereAndEqProperties = EntityUtils.getWhereProperties(findPermission, Attributes.code.name());

		final Model model = ModelUtils.newModel(new ModelArgs(findPermission, whereAndEqProperties));

		if (MapUtils.isNotEmpty(findPermission.getAttrs())) {
			model.putAll(findPermission.getAttrs());
		}

		model.putTrue(Model.Keys.whereAndBetween.stringValue(), Attributes.sysdate.name());

		return ContextHolder.getBean(JdbcTemplateSupport.class).find(mappedClass, SqlIds.findByCode.id(), model);
	}

	@Override
	public <P> P findById(final Class<P> mappedClass, final PermissionDto findPermission) {
		final String[] whereAndEqProperties = EntityUtils.getWhereProperties(findPermission);

		final Model model = ModelUtils.newModel(new ModelArgs(findPermission, whereAndEqProperties).setIsSimple(true));

		if (MapUtils.isNotEmpty(findPermission.getAttrs())) {
			model.putAll(findPermission.getAttrs());
		}

		return ContextHolder.getBean(JdbcTemplateSupport.class).find(mappedClass, SqlIds.findById.id(), model);
	}

	@Override
	public <P> List<P> findListByLikeCode(final Class<P> mappedClass, final PermissionDto findListPermission) {
		final Model model = ModelUtils.newModel(new ModelArgs(findListPermission).setIsSimple(true));

		if (MapUtils.isNotEmpty(findListPermission.getAttrs())) {
			model.putAll(findListPermission.getAttrs());
		}

		return ContextHolder.getBean(JdbcTemplateSupport.class).findList(mappedClass, SqlIds.findByLikeCode.id(), model);
	}

	@Override
	public <P> List<P> findListBySiteId(final Class<P> mappedClass, final String siteId) {
		final Map<String, Object> model = Maps.newHashMap();

		model.put(Attributes.siteId.name(), siteId);

		return ContextHolder.getBean(JdbcTemplateSupport.class).findList(mappedClass, SqlIds.findBySiteId.id(), model);
	}

	@Override
	public <P> List<P> findListBySiteIdAndRoleIdList(final Class<P> mappedClass, final String siteId, final List<String> roleIdList) {
		final Map<String, Object> model = Maps.newHashMap();

		model.put(Attributes.siteId.name(), siteId);
		model.put("roleIds", StringUtils.join(roleIdList, ","));

		return ContextHolder.getBean(JdbcTemplateSupport.class).findList(mappedClass, SqlIds.findBySiteIdAndRoleIdList.id(), model);
	}

	@Override
	public <P> List<P> findListBySiteIdAndTypeCode(final Class<P> mappedClass, final String siteId, final String typeCode) {
		final Map<String, Object> model = Maps.newHashMap();

		model.put(Attributes.siteId.name(), siteId);
		model.put(Attributes.typeCode.name(), typeCode);

		return ContextHolder.getBean(JdbcTemplateSupport.class).findList(mappedClass, SqlIds.findBySiteIdAndTypeCode.id(), model);
	}

	@Override
	public <P> List<P> findListBySiteIdAndTypeId(final Class<P> mappedClass, final String siteId, final String typeId) {
		final Map<String, Object> model = Maps.newHashMap();

		model.put(Attributes.siteId.name(), siteId);
		model.put(Attributes.typeId.name(), typeId);

		return ContextHolder.getBean(JdbcTemplateSupport.class).findList(mappedClass, SqlIds.findBySiteIdAndTypeId.id(), model);
	}

	@Override
	public int insertByCode(final PermissionDto insertPermission) {
		if (StringUtils.isBlank(insertPermission.getId())) {
			insertPermission.setId(UUID.randomUUID().toString());
		}

		final Model model = ModelUtils.newModel(new ModelArgs(Model.Keys.insert.stringValue(), insertPermission));

		if (MapUtils.isNotEmpty(insertPermission.getAttrs())) {
			model.putAll(insertPermission.getAttrs());
		}

		model.putTrue(Model.Keys.whereAndBetween.stringValue(), Attributes.sysdate.name());

		return ContextHolder.getBean(JdbcTemplateSupport.class).update(SqlIds.insertByCode.id(), model);
	}

	@Override
	public <P> PaginationDto<P> paginationByLikeCode(final Class<P> mappedClass, final PermissionDto paginationPermission) {
		final Model model = ModelUtils.newModel(new ModelArgs(paginationPermission).setIsSimple(true));

		if (MapUtils.isNotEmpty(paginationPermission.getAttrs())) {
			model.putAll(paginationPermission.getAttrs());
		}

		return ContextHolder.getBean(JdbcTemplateSupport.class).pagination(mappedClass, new PaginationArgs(SqlIds.readByLikeCode.id(), SqlIds.findByLikeCode.id(), paginationPermission), model);
	}

	@Override
	public Integer readByCodeNqIdForCount(final PermissionDto readPermission) {
		final String[] whereAndEqProperties = { Attributes.code.name() };

		final Model model = ModelUtils.newModel(new ModelArgs(readPermission, whereAndEqProperties));

		if (MapUtils.isNotEmpty(readPermission.getAttrs())) {
			model.putAll(readPermission.getAttrs());
		}

		final String[] whereAndNqProperties = EntityUtils.getWhereProperties(readPermission);

		if (ArrayUtils.isNotEmpty(whereAndNqProperties)) {
			ModelUtils.put(model, new ModelArgs(Model.Keys.whereAndNq.stringValue(), readPermission, whereAndNqProperties));
		}

		model.putTrue(Model.Keys.whereAndBetween.stringValue(), Attributes.sysdate.name());

		return ContextHolder.getBean(JdbcTemplateSupport.class).read(Integer.class, SqlIds.readByCode.id(), model);
	}

	@Override
	public List<String> readCodeListBySiteIdAndTypeCode(final String siteId, final String typeCode) {
		final Map<String, Object> model = Maps.newHashMap();

		model.put(Attributes.siteId.name(), siteId);
		model.put(Attributes.typeCode.name(), typeCode);

		return ContextHolder.getBean(JdbcTemplateSupport.class).readList(String.class, SqlIds.readCodeBySiteIdAndTypeCode.id(), model);
	}

	@Override
	public <P> P saveByIdOrCode(final Class<P> mappedClass, final PermissionDto savePermission) {
		final P oldPermission = this.findByCodeOrId(mappedClass, savePermission);

		if (oldPermission == null) {
			this.insertByCode(savePermission);

			return this.findByCodeOrId(mappedClass, savePermission);
		}

		final int updateCount = this.updateByCode(savePermission, oldPermission);

		if (updateCount < 1) {
			return oldPermission;
		}

		return this.findByCodeOrId(mappedClass, savePermission);
	}

	@Override
	public int updateByCode(final PermissionDto updatePermission) {
		final PermissionDto oldPermission = this.findByCodeOrId(PermissionDto.class, updatePermission);

		return this.updateByCode(updatePermission, oldPermission);
	}

	private <P> int updateByCode(final PermissionDto updatePermission, final P oldPermission) {
		if (oldPermission == null) {
			return 0;
		}

		final String[] useProperties = EntityUtils.addNotNullTimeSegmentProperties(new String[] { Attributes.parentId.name(), Attributes.typeId.name(), Attributes.code.name(), Attributes.name.name(), Attributes.value.name(), Attributes.remark.name() }, updatePermission);

		final String[] updateProperties = com.cardone.common.util.BeanUtils.diffProperties(updatePermission, oldPermission, useProperties);

		if (ArrayUtils.isEmpty(updateProperties)) {
			return 0;
		}

		final String[] whereAndEqProperties = EntityUtils.getWhereProperties(oldPermission, Attributes.id.name());

		com.cardone.common.util.BeanUtils.copyProperties(oldPermission, updatePermission, whereAndEqProperties);

		final Model model = ModelUtils.newModel(new ModelArgs(Model.Keys.update.stringValue(), updatePermission, updateProperties), new ModelArgs(updatePermission, whereAndEqProperties));

		if (MapUtils.isNotEmpty(updatePermission.getAttrs())) {
			model.putAll(updatePermission.getAttrs());
		}

		return ContextHolder.getBean(JdbcTemplateSupport.class).update(SqlIds.updateByCode.id(), model);
	}
}